﻿Imports System.ComponentModel

Public Class main
    WithEvents fm As New Firmata.FirmataVB
    Private Delegate Sub myDel()
    Dim mymy As New myDel(AddressOf recData)

#Region "IO flags Decalrations"

#Region "Output"
    Public oStartStop_Tanks() As Boolean = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
    Public oStartStop_TanksSpeeds() As Boolean = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
    Public oSpeed_TankInverter As Byte = 0
    Public oStartStop_ScaleScrewMotor As Boolean = False
    Public oOpenClose_MixerGate As Boolean = False
    Public oStartStop_Mixer As Boolean = False
    Public oStartStop_Siren As Boolean = False
    Public oStartStop_Sakia1 As Boolean = False

    Public oStartStop_Hammer As Boolean = False
    Public oSpeed_TankInverterEnable As Boolean = False
    Public oAlerterBanks As Boolean = False
#End Region

#Region "Input"
    Public iStartStop_MixerACK As Boolean = False
    Public iOverload_TankInverter As Boolean = False
    Public iLimit_HighStorage As Boolean = False
    Public iLimit_LowStorage As Boolean = False
    Public iOverload_Sakia As Boolean = False
    Public iOverload_ScaleScrewMotor As Boolean = False
    Public iLimit_MixerGateClosed As Boolean = False
    Public iOverLoad_Sakia1 As Boolean = False

    Public sScaleReading As Double = 0.0
#End Region

#Region "Pin Const Definitions"
    Public poStartStop_Tanks() As Integer = {29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51}
    Public Const poSpeed_TankInverterEnable As Integer = 53
    Public Const poSpeed_TankInverter As Integer = 6
    Public Const poStartStop_ScaleScrewMotor As Integer = 24
    Public Const poOpenClose_MixerGate As Integer = 25
    Public Const poStartStop_Mixer As Integer = 26
    Public Const poStartStop_Siren As Integer = 27
    Public Const poStartStop_Sakia1 As Integer = 28

    Public Const poStartStop_Hammer As Integer = 38

    Public Const poAlerterBankA As Integer = 14
    Public Const poAlerterBankB As Integer = 22

    Public Const piReservedBankA As Integer = 15
    Public Const piReservedBankB As Integer = 23

    Public Const piStartStop_MixerACK As Integer = 8
    Public Const piOverload_TankInverter As Integer = 9
    Public Const piLimit_HighStorage As Integer = 10
    Public Const piLimit_LowStorage As Integer = 11
    Public Const piOverload_Sakia As Integer = 16
    Public Const piOverload_ScaleScrewMotor As Integer = 17
    Public Const piLimit_MixerGateClosed As Integer = 18
    Public Const piOverload_Sakia1 As Integer = 19
#End Region

#End Region

#Region "State Variables"
    Public TanksSpeedsLow() As Byte = {100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100}
    Public TanksSpeedsHigh() As Byte = {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}
    Public TanksSpeedsTotalDrop() As Double = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5, 0.5}
    Public TanksSpeedsHighDrop() As Double = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.0, 1.0}
    Public TanksTotalDrop() As Double = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
    Public LastWeightBeforeDrop As Double = 0.0
    Public NumberOfBatchesLeft As Integer = 1
    Public MixTime As Integer = 2
    Public MixerGateOpenTime As Integer = 2
    Public inMix As Boolean = False

    Public stateMessage1 As String = ""
    Public stateMessage2 As String = ""
    Public arrAlarms As New ArrayList
    Public fWorking As Boolean = False
    Public fForceStop As Boolean = False
    Public fPause As Boolean = False

    Public cTankZeroedValue As Double = 2.0

    Public BatchNo As Integer = 0

    Public reportRecordID As Integer = 0

    Public TerminateConnection As Boolean = False
    Public sConnectToScale As Boolean = False
    Public sComPort As String = "COM16"
    Public fComPort As String = "COM20"
#End Region

#Region "Functions"
#Region "Connection"
    Private Sub ConnectAndConfigureIO()
        If sConnectToScale Then
            spScale.PortName = sComPort
            spScale.Open()
        End If
        fm.Connect(fComPort, 57600)
        ConfigureIOPins()
    End Sub

    Private Sub ConfigureIOPins()
        ''Output pin
        fm.PinMode(poStartStop_Tanks(0), Firmata.FirmataVB.OUTUPT)
        fm.PinMode(poStartStop_Tanks(1), Firmata.FirmataVB.OUTUPT)
        fm.PinMode(poStartStop_Tanks(2), Firmata.FirmataVB.OUTUPT)
        fm.PinMode(poStartStop_Tanks(3), Firmata.FirmataVB.OUTUPT)
        fm.PinMode(poStartStop_Tanks(4), Firmata.FirmataVB.OUTUPT)
        fm.PinMode(poStartStop_Tanks(5), Firmata.FirmataVB.OUTUPT)
        fm.PinMode(poStartStop_Tanks(6), Firmata.FirmataVB.OUTUPT)
        fm.PinMode(poStartStop_Tanks(7), Firmata.FirmataVB.OUTUPT)
        fm.PinMode(poStartStop_Tanks(8), Firmata.FirmataVB.OUTUPT)
        fm.PinMode(poStartStop_Tanks(9), Firmata.FirmataVB.OUTUPT)
        fm.PinMode(poStartStop_Tanks(10), Firmata.FirmataVB.OUTUPT)
        fm.PinMode(poStartStop_Tanks(11), Firmata.FirmataVB.OUTUPT)

        fm.PinMode(poSpeed_TankInverter, Firmata.FirmataVB.PWM)
        fm.PinMode(poSpeed_TankInverterEnable, Firmata.FirmataVB.OUTUPT)
        fm.PinMode(poStartStop_ScaleScrewMotor, Firmata.FirmataVB.OUTUPT)
        fm.PinMode(poOpenClose_MixerGate, Firmata.FirmataVB.OUTUPT)
        fm.PinMode(poStartStop_Mixer, Firmata.FirmataVB.OUTUPT)
        fm.PinMode(poStartStop_Siren, Firmata.FirmataVB.OUTUPT)
        fm.PinMode(poStartStop_Sakia1, Firmata.FirmataVB.OUTUPT)

        ''reserved pins
        fm.PinMode(poAlerterBankA, Firmata.FirmataVB.OUTUPT)
        fm.PinMode(poAlerterBankB, Firmata.FirmataVB.OUTUPT)
        fm.PinMode(piReservedBankA, Firmata.FirmataVB.INPUT)
        fm.DigitalWrite(piReservedBankA, Firmata.FirmataVB.HIGH)
        fm.PinMode(piReservedBankB, Firmata.FirmataVB.INPUT)
        fm.DigitalWrite(piReservedBankB, Firmata.FirmataVB.HIGH)

        ''Input
        fm.PinMode(piStartStop_MixerACK, Firmata.FirmataVB.INPUT)
        fm.DigitalWrite(piStartStop_MixerACK, Firmata.FirmataVB.HIGH)
        fm.PinMode(piOverload_TankInverter, Firmata.FirmataVB.INPUT)
        fm.DigitalWrite(piOverload_TankInverter, Firmata.FirmataVB.HIGH)
        fm.PinMode(piLimit_HighStorage, Firmata.FirmataVB.INPUT)
        fm.DigitalWrite(piLimit_HighStorage, Firmata.FirmataVB.HIGH)
        fm.PinMode(piLimit_LowStorage, Firmata.FirmataVB.INPUT)
        fm.DigitalWrite(piLimit_LowStorage, Firmata.FirmataVB.HIGH)
        fm.PinMode(piOverload_Sakia, Firmata.FirmataVB.INPUT)
        fm.DigitalWrite(piOverload_Sakia, Firmata.FirmataVB.HIGH)
        fm.PinMode(piOverload_ScaleScrewMotor, Firmata.FirmataVB.INPUT)
        fm.DigitalWrite(piOverload_ScaleScrewMotor, Firmata.FirmataVB.HIGH)
        fm.PinMode(piLimit_MixerGateClosed, Firmata.FirmataVB.INPUT)
        fm.DigitalWrite(piLimit_MixerGateClosed, Firmata.FirmataVB.HIGH)
        fm.PinMode(piOverload_Sakia1, Firmata.FirmataVB.INPUT)
        fm.DigitalWrite(piOverload_Sakia1, Firmata.FirmataVB.HIGH)

        ''oStartStop_Tanks = fm.DigitalRead(poStartStop_Tanks))

        oStartStop_ScaleScrewMotor = fm.DigitalRead(poStartStop_ScaleScrewMotor)
        oOpenClose_MixerGate = fm.DigitalRead(poOpenClose_MixerGate)
        oStartStop_Mixer = fm.DigitalRead(poStartStop_Mixer)
        oStartStop_Siren = fm.DigitalRead(poStartStop_Siren)
        oStartStop_Sakia1 = fm.DigitalRead(poStartStop_Sakia1)
        iStartStop_MixerACK = fm.DigitalRead(piStartStop_MixerACK)
        iOverload_TankInverter = fm.DigitalRead(piOverload_TankInverter)
        iLimit_HighStorage = fm.DigitalRead(piLimit_HighStorage)
        iLimit_LowStorage = fm.DigitalRead(piLimit_LowStorage)
        iOverload_Sakia = fm.DigitalRead(piOverload_Sakia)
        iOverload_ScaleScrewMotor = fm.DigitalRead(piOverload_ScaleScrewMotor)
        iLimit_MixerGateClosed = fm.DigitalRead(piLimit_MixerGateClosed)
        iOverLoad_Sakia1 = fm.DigitalRead(piOverload_Sakia1)

        fm.DigitalPortReport(0, 1)
        fm.DigitalPortReport(1, 1)
        fm.DigitalPortReport(2, 1)
        fm.DigitalPortReport(3, 1)
        fm.DigitalPortReport(4, 1)
        fm.DigitalPortReport(5, 1)
        fm.DigitalPortReport(6, 1)

        tmrUpdateOutput.Enabled = True

    End Sub

    Private Sub Disconnect()
        TerminateConnection = True
        tmrUpdateOutput.Enabled = False
        SleepSecs(1)
        fm.Disconnect()

        While spScale.IsOpen

        End While
        TerminateConnection = False
    End Sub
#End Region

#Region "Helper functions"

    Private Sub ResetAllOutputs()
        oStartStop_Tanks = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
        oStartStop_TanksSpeeds = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
        oSpeed_TankInverter = 0
        oStartStop_ScaleScrewMotor = False
        oOpenClose_MixerGate = False
        oStartStop_Mixer = False
        oStartStop_Siren = False
        oStartStop_Sakia1 = False

        oStartStop_Hammer = False
    End Sub

    Private Sub SetTankSpeed(ByVal tankNo As Integer, ByVal tankSpeed As Boolean)
        SetElementAndResetTheRest(oStartStop_Tanks, tankNo, True, False)
        SetElementAndResetTheRest(oStartStop_TanksSpeeds, tankNo, tankSpeed, False)
        oSpeed_TankInverter = If(tankSpeed, TanksSpeedsHigh(tankNo), TanksSpeedsLow(tankNo))
    End Sub

    Private Sub StopAllTanks()
        For i As Integer = 0 To oStartStop_Tanks.Length - 1
            oStartStop_Tanks(i) = False
        Next
        For i As Integer = 0 To oStartStop_TanksSpeeds.Length - 1
            oStartStop_TanksSpeeds(i) = False
        Next
        oSpeed_TankInverter = 0
    End Sub

    Private Sub SetElementAndResetTheRest(ByRef obj() As Boolean, ByVal setItemIndex As Integer, ByVal setValue As Object, ByVal resetValue As Object)
        For i As Integer = 0 To obj.Length - 1
            obj(i) = If(i = setItemIndex, setValue, resetValue)
        Next
    End Sub

    Private Sub SleepSecs(ByVal secs As Double)
        Threading.Thread.Sleep(secs * 1000)
    End Sub

    Private Sub recData()
        Dim s As String = spScale.ReadLine()
        Dim dl() As String = Split(s, ",")
        If dl.Length >= 3 Then
            sScaleReading = Val(dl(2))
        End If
    End Sub

    Private Function checkForStopSignalAndHold(ByVal hold As Boolean, Optional ByVal cScrew As Boolean = False, Optional ByVal HoldScrew As Boolean = False, Optional ByVal cSakia1 As Boolean = False, Optional ByVal HoldSakia1 As Boolean = False, Optional ByVal cMixer As Boolean = False, Optional ByVal HoldMixer As Boolean = False, Optional ByVal cInverter As Boolean = False) As Boolean
        If hold Then
            Dim loStartStop_ScaleScrewMotor As Boolean = oStartStop_ScaleScrewMotor
            Dim loStartStop_Sakia1 As Boolean = oStartStop_Sakia1
            Dim loStartStop_Mixer As Boolean = oStartStop_Mixer
            While hold
                'hold = Not (((Not cScrew) OrElse Not iOverload_ScaleScrewMotor) And ((Not cSakia1) OrElse Not iOverLoad_Sakia1) And ((Not cMixer) OrElse (iStartStop_MixerACK And Not iOverload_Sakia)))
                hold = Not cInverter And ((cScrew And iOverload_ScaleScrewMotor) Or (cSakia1 And iOverLoad_Sakia1) Or (cMixer And (Not iStartStop_MixerACK Or iOverload_Sakia)))

                If cInverter Then
                    hold = iOverload_TankInverter
                    If hold Then oSpeed_TankInverter = 0
                Else
                    If HoldScrew And hold Then oStartStop_ScaleScrewMotor = Not (iOverload_Sakia Or Not iStartStop_MixerACK Or iOverLoad_Sakia1 Or iOverload_ScaleScrewMotor)
                    If HoldSakia1 And hold Then oStartStop_Sakia1 = Not (iOverload_Sakia Or Not iStartStop_MixerACK Or iOverLoad_Sakia1 Or iOverload_ScaleScrewMotor)
                    If HoldMixer And hold Then oStartStop_Mixer = Not (iOverload_Sakia Or Not iStartStop_MixerACK)
                End If
                If checkForStopSignalAndHold(False) Then Return fForceStop
            End While
            oStartStop_ScaleScrewMotor = loStartStop_ScaleScrewMotor
            oStartStop_Sakia1 = loStartStop_Sakia1
            oStartStop_Mixer = loStartStop_Mixer
        End If
        Return fForceStop
    End Function

#End Region

#Region "Run"
    Private Sub StartOperation()
        fWorking = True
        fForceStop = False
        'bgwStart.RunWorkerAsync()
        bgwTankStarter.RunWorkerAsync(0)
    End Sub

    Private Sub StopOperation()
        bgwStartMixer.CancelAsync()
        bgwTanks.CancelAsync()
        bgwTankStarter.CancelAsync()

        StopAllTanks()

        oStartStop_ScaleScrewMotor = False
        oOpenClose_MixerGate = False
        'oStartStop_Mixer = False mohammed requested this
        oStartStop_Siren = False
        oStartStop_Sakia1 = False

        fForceStop = True
        fWorking = False
    End Sub

#End Region

#End Region

    Private Sub btnConnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnConnect.Click
        If btnConnect.Text = "Connect" Then
            btnConnect.Text = "Disconnect"
            btnConnect.BackColor = Color.Red
            ConnectAndConfigureIO()

        ElseIf btnConnect.Text = "Disconnect" Then
            btnConnect.Text = "Connect"
            btnConnect.BackColor = Color.Chartreuse
            Disconnect()
        End If
    End Sub

    Private Sub btnStart_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnStart.Click
        If BatchNo = Nothing Then
            MsgBox("Please Choose Batch", MsgBoxStyle.OkOnly, "Error")
            Exit Sub
        End If
        If btnStart.Text = "Start" Then
            If iStartStop_MixerACK Then
                btnStart.Text = "Stop"
                btnStart.BackColor = Color.Red
                txtNumberOfBatchesLeft.Enabled = False
                txtMixTime.Enabled = False
                txtMixerGateOpenTime.Enabled = False
                txtTankZeroedValue.Enabled = False
                NumberOfBatchesLeft = Val(txtNumberOfBatchesLeft.Text)
                MixTime = Val(txtMixTime.Text)
                MixerGateOpenTime = Val(txtMixerGateOpenTime.Text)
                cTankZeroedValue = Val(txtTankZeroedValue.Text)
                TanksTotalDrop = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
                oOpenClose_MixerGate = False
                oStartStop_Sakia1 = False
                oStartStop_ScaleScrewMotor = False
                StartOperation()
            End If
        ElseIf btnStart.Text = "Stop" Then
            btnStart.Text = "Start"
            btnStart.BackColor = Color.Chartreuse
            txtNumberOfBatchesLeft.Enabled = True
            txtMixTime.Enabled = True
            txtMixerGateOpenTime.Enabled = True
            txtTankZeroedValue.Enabled = True
            StopOperation()
        End If
    End Sub

    ''' <summary>
    ''' Update the drawing with the values of the flags
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub tmrUpdateDrawing_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tmrUpdateDrawing.Tick
        ''Time
        DTB1.Value = Date.Now

        ''Mixer
        PictureBox33.Visible = Not oStartStop_Mixer
        PictureBox32.Visible = Not oStartStop_Mixer
        PictureBox31.Visible = Not oStartStop_Mixer
        'PictureBox30.Visible = Not oStartStop_Mixer
        PictureBox29.Visible = Not oStartStop_Mixer
        PictureBox24.Visible = Not oStartStop_Mixer
        PictureBox23.Visible = Not oStartStop_Mixer
        PictureBox20.Visible = Not oStartStop_Mixer
        PictureBox17.Visible = Not oStartStop_Mixer
        btnMixer_StartStop.BackColor = If(oStartStop_Mixer, Color.Green, Color.Red)
        btnMixer_StartStop.Enabled = Not fWorking
        btnMixerGate_OpenClose.BackColor = If(oOpenClose_MixerGate, Color.Green, Color.Red)
        btnMixerGate_OpenClose.Enabled = Not fWorking
        btnSakia1Screw_StartStop.BackColor = If(oStartStop_Sakia1, Color.Green, Color.Red)
        btnSakia1Screw_StartStop.Enabled = Not fWorking
        btnPauseResume.BackColor = If(fPause, Color.Red, Color.Green)

        ''hammer
        PictureBox80.Visible = oStartStop_Hammer
        'ack
        PictureBox78.Visible = iStartStop_MixerACK

        ''mixergate
        PictureBox22.Visible = Not oOpenClose_MixerGate
        PictureBox21.Visible = Not oOpenClose_MixerGate

        ''Scale iOverload_ScaleScrewMotor motor
        PictureBox16.Visible = Not oStartStop_ScaleScrewMotor

        ''sakia1
        PictureBox65.Visible = Not oStartStop_Sakia1
        PictureBox68.Visible = Not oStartStop_Sakia1
        PictureBox66.Visible = Not oStartStop_Sakia1

        ''HighStorag
        PictureBox76.Visible = Not iLimit_HighStorage

        ''lowStorag
        PictureBox77.Visible = Not iLimit_LowStorage

        ''Tanks
        PictureBox49.Visible = oStartStop_Tanks(0) : PictureBox49.BackColor = If(oStartStop_TanksSpeeds(0), Color.Red, Color.Blue)
        PictureBox50.Visible = oStartStop_Tanks(1) : PictureBox50.BackColor = If(oStartStop_TanksSpeeds(1), Color.Red, Color.Blue)
        PictureBox51.Visible = oStartStop_Tanks(2) : PictureBox51.BackColor = If(oStartStop_TanksSpeeds(2), Color.Red, Color.Blue)
        PictureBox52.Visible = oStartStop_Tanks(3) : PictureBox52.BackColor = If(oStartStop_TanksSpeeds(3), Color.Red, Color.Blue)
        PictureBox53.Visible = oStartStop_Tanks(4) : PictureBox53.BackColor = If(oStartStop_TanksSpeeds(4), Color.Red, Color.Blue)
        PictureBox54.Visible = oStartStop_Tanks(5) : PictureBox54.BackColor = If(oStartStop_TanksSpeeds(5), Color.Red, Color.Blue)
        PictureBox55.Visible = oStartStop_Tanks(6) : PictureBox55.BackColor = If(oStartStop_TanksSpeeds(6), Color.Red, Color.Blue)
        PictureBox56.Visible = oStartStop_Tanks(7) : PictureBox56.BackColor = If(oStartStop_TanksSpeeds(7), Color.Red, Color.Blue)
        PictureBox57.Visible = oStartStop_Tanks(8) : PictureBox57.BackColor = If(oStartStop_TanksSpeeds(8), Color.Red, Color.Blue)
        PictureBox58.Visible = oStartStop_Tanks(9) : PictureBox58.BackColor = If(oStartStop_TanksSpeeds(9), Color.Red, Color.Blue)
        PictureBox59.Visible = oStartStop_Tanks(10) : PictureBox59.BackColor = If(oStartStop_TanksSpeeds(10), Color.Red, Color.Blue)
        PictureBox60.Visible = oStartStop_Tanks(11) : PictureBox60.BackColor = If(oStartStop_TanksSpeeds(11), Color.Red, Color.Blue)

        ''MixerGateClosed()

        PictureBox79.Visible = iLimit_MixerGateClosed

        ''Overload_TankInverter
        Label10.Visible = iOverload_TankInverter

        ''oveload sakia
        Label4.Visible = iOverload_Sakia

        ''Overload_scale screw motor
        Label6.Visible = iOverload_ScaleScrewMotor

        ''Overload_Sakia1
        Label7.Visible = iOverLoad_Sakia1

        txtScales.Text = sScaleReading

        lblStateMessage1.Text = stateMessage1
        lblStateMessage2.Text = stateMessage2

        ''tankDrop
        txtTank1d.Text = TanksTotalDrop(0)
        txtTank2d.Text = TanksTotalDrop(1)
        txtTank3d.Text = TanksTotalDrop(2)
        txtTank4d.Text = TanksTotalDrop(3)
        txtTank5d.Text = TanksTotalDrop(4)
        txtTank6d.Text = TanksTotalDrop(5)
        txtTank7d.Text = TanksTotalDrop(6)
        txtTank8d.Text = TanksTotalDrop(7)
        txtTank9d.Text = TanksTotalDrop(8)
        txtTank10d.Text = TanksTotalDrop(9)
        txtTank11d.Text = TanksTotalDrop(10)
        txtTank12d.Text = TanksTotalDrop(11)

        ''batches left
        lblBatchesLeft.Text = NumberOfBatchesLeft

        ''alarms


        btnPauseResume.Text = If(fPause, "Resume", "Pause")


        For Each s As String In arrAlarms
            lstAlarms.Items.Insert(0, s)
        Next
        arrAlarms.Clear()
    End Sub

    ''' <summary>
    ''' Handler for digitalpinChange Report
    ''' </summary>
    ''' <param name="portNumber"></param>
    ''' <param name="portData"></param>
    ''' <remarks></remarks>
    Private Sub FirmataVB1_DigitalMessageReceieved(ByVal portNumber As Integer, ByVal portData As Integer) Handles fm.DigitalMessageReceieved
        fabAssignDigitalInput(portNumber, portData, piStartStop_MixerACK, iStartStop_MixerACK)
        fabAssignDigitalInput(portNumber, portData, piOverload_TankInverter, iOverload_TankInverter)
        fabAssignDigitalInput(portNumber, portData, piLimit_HighStorage, iLimit_HighStorage)
        fabAssignDigitalInput(portNumber, portData, piLimit_LowStorage, iLimit_LowStorage)
        fabAssignDigitalInput(portNumber, portData, piOverload_Sakia, iOverload_Sakia)
        fabAssignDigitalInput(portNumber, portData, piOverload_ScaleScrewMotor, iOverload_ScaleScrewMotor)
        fabAssignDigitalInput(portNumber, portData, piLimit_MixerGateClosed, iLimit_MixerGateClosed)
        fabAssignDigitalInput(portNumber, portData, piOverload_Sakia1, iOverLoad_Sakia1)

        If Not fWorking Then
            If oStartStop_ScaleScrewMotor Then oStartStop_ScaleScrewMotor = Not (iOverload_Sakia Or Not iStartStop_MixerACK Or iOverLoad_Sakia1 Or iOverload_ScaleScrewMotor)
            If oStartStop_Sakia1 Then oStartStop_Sakia1 = Not (iOverload_Sakia Or Not iStartStop_MixerACK Or iOverLoad_Sakia1 Or iOverload_ScaleScrewMotor)
            If oStartStop_Mixer Then oStartStop_Mixer = Not (iOverload_Sakia Or Not iStartStop_MixerACK)

        End If
    End Sub

    ''' <summary>
    ''' Read and bang incomming data into pins
    ''' </summary>
    ''' <param name="portNumber"></param>
    ''' <param name="portData"></param>
    ''' <param name="pin"></param>
    ''' <param name="dataFlag"></param>
    ''' <remarks></remarks>
    Private Sub fabAssignDigitalInput(ByVal portNumber As Integer, ByVal portData As Integer, ByVal pin As Integer, ByRef dataFlag As Boolean)
        If portNumber = Int(pin / 8) Then
            dataFlag = (portData And (2 ^ (pin Mod 8))) > 0
        End If
    End Sub

    ''' <summary>
    ''' Update the output pins with the data in the flags
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub tmrUpdateOutput_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tmrUpdateOutput.Tick
        fm.AnalogWrite(poSpeed_TankInverter, oSpeed_TankInverter)
        fm.DigitalWrite(poSpeed_TankInverterEnable, oSpeed_TankInverter > 0)
        fm.DigitalWrite(poStartStop_ScaleScrewMotor, oStartStop_ScaleScrewMotor)
        fm.DigitalWrite(poOpenClose_MixerGate, oOpenClose_MixerGate)
        fm.DigitalWrite(poStartStop_Mixer, oStartStop_Mixer)
        fm.DigitalWrite(poStartStop_Siren, oStartStop_Siren)
        fm.DigitalWrite(poStartStop_Sakia1, oStartStop_Sakia1)
        ''tanks
        fm.DigitalWrite(poStartStop_Tanks(0), oStartStop_Tanks(0))
        fm.DigitalWrite(poStartStop_Tanks(1), oStartStop_Tanks(1))
        fm.DigitalWrite(poStartStop_Tanks(2), oStartStop_Tanks(2))
        fm.DigitalWrite(poStartStop_Tanks(3), oStartStop_Tanks(3))
        fm.DigitalWrite(poStartStop_Tanks(4), oStartStop_Tanks(4))
        fm.DigitalWrite(poStartStop_Tanks(5), oStartStop_Tanks(5))
        fm.DigitalWrite(poStartStop_Tanks(6), oStartStop_Tanks(6))
        fm.DigitalWrite(poStartStop_Tanks(7), oStartStop_Tanks(7))
        fm.DigitalWrite(poStartStop_Tanks(8), oStartStop_Tanks(8))
        fm.DigitalWrite(poStartStop_Tanks(9), oStartStop_Tanks(9))
        fm.DigitalWrite(poStartStop_Tanks(10), oStartStop_Tanks(10))
        fm.DigitalWrite(poStartStop_Tanks(11), oStartStop_Tanks(11))

        fm.DigitalWrite(poStartStop_Hammer, oStartStop_Hammer)

        fm.DigitalWrite(poAlerterBankA, oAlerterBanks)
        fm.DigitalWrite(poAlerterBankB, oAlerterBanks)
        oAlerterBanks = Not oAlerterBanks
    End Sub

#Region "for degubbing"
    Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
        sScaleReading = Val(TextBox22.Text)
    End Sub

    Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
        TextBox22.Text = Val(TextBox22.Text) + 100
        Button3_Click(Nothing, Nothing)
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        TextBox22.Text = Val(TextBox22.Text) + 50
        Button3_Click(Nothing, Nothing)
    End Sub
#End Region

    Private Sub bgwTanks_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgwTanks.DoWork
        Dim tankNo As Integer? = CInt(e.Argument)
        Dim recurTimes As Integer = 0
        Dim recurWeight As Double = 0
        Dim scaleNotch As Double = 0.0
        If tankNo Is Nothing Then
            Console.WriteLine(String.Format("Tank number error: No tank number received"))
            Exit Sub
        End If

        If checkForStopSignalAndHold(False) Then e.Cancel = True : Exit Sub

        If tankNo = 0 Then
            reportRecordID = InsertBatchRecord(BatchNo, txtScaled.Text, Now)
        End If

        If checkForStopSignalAndHold(False) Then e.Cancel = True : Exit Sub

        'start tank with high speed
        SetTankSpeed(tankNo, True)

        'wait till weight is met
        stateMessage1 = String.Format("Weight {0} on Tank{1}", "HIGH", tankNo + 1)
        LastWeightBeforeDrop = sScaleReading
        scaleNotch = sScaleReading
        While sScaleReading - LastWeightBeforeDrop < TanksSpeedsHighDrop(tankNo)
            TanksTotalDrop(tankNo) = sScaleReading - scaleNotch
            recurWeight = sScaleReading - LastWeightBeforeDrop
            SleepSecs(1)
            If checkForStopSignalAndHold(True, cInverter:=True) Then e.Cancel = True : Exit Sub
            While fPause
                oSpeed_TankInverter = 0
            End While
            SetTankSpeed(tankNo, True)
            If recurWeight = sScaleReading - LastWeightBeforeDrop Then
                recurTimes += 1
                If recurTimes = 10 Then
                    ''tank is stuck
                    oStartStop_Hammer = True
                    Dim unit As String = String.Format("Tank{0}", tankNo + 1)
                    Dim msg As String = String.Format("Tank{0} is Stuck", tankNo + 1)
                    RaiseAlarm(True, True, False, unit, msg, BatchNo, msg)
                    arrAlarms.Add(String.Format("{0}: {1} - {2}", Now, unit, msg))
                    stateMessage1 = msg
                End If
            Else
                recurTimes = 0
            End If
        End While
        TanksTotalDrop(tankNo) = sScaleReading - scaleNotch

        'start tank with low speed
        SetTankSpeed(tankNo, False)

        'wait till weight is met
        stateMessage1 = String.Format("Weight {0} on Tank{1}", "LOW", tankNo + 1)
        'LastWeightBeforeDrop = sScaleReading
        While sScaleReading - LastWeightBeforeDrop < TanksSpeedsTotalDrop(tankNo)
            TanksTotalDrop(tankNo) = sScaleReading - scaleNotch
            recurWeight = sScaleReading - LastWeightBeforeDrop
            SleepSecs(1)
            If checkForStopSignalAndHold(True, cInverter:=True) Then e.Cancel = True : Exit Sub
            While fPause
                oSpeed_TankInverter = 0
            End While
            SetTankSpeed(tankNo, False)
            If recurWeight = sScaleReading - LastWeightBeforeDrop Then
                recurTimes += 1
                If recurTimes = 10 Then
                    ''tank is stuck
                    oStartStop_Hammer = True
                    Dim unit As String = String.Format("Tank{0}", tankNo + 1)
                    Dim msg As String = String.Format("Tank{0} is Stuck", tankNo + 1)
                    RaiseAlarm(True, True, False, unit, msg, BatchNo, msg)
                    arrAlarms.Add(String.Format("{0}: {1} - {2}", Now, unit, msg))
                    stateMessage1 = msg
                End If
            Else
                recurTimes = 0
            End If
        End While
        TanksTotalDrop(tankNo) = sScaleReading - scaleNotch

        If checkForStopSignalAndHold(False) Then e.Cancel = True : Exit Sub

        'If checkForStopSignalAndHold() Then e.Cancel = True : Exit Sub

        'stop tank
        StopAllTanks()

        stateMessage1 = String.Format("Tank{0} is Done", tankNo + 1)

        If checkForStopSignalAndHold(False) Then e.Cancel = True : Exit Sub

        'wait 2 secs
        SleepSecs(2)

        InsertBatchRecordDetail(reportRecordID, tankNo + 1, TanksTotalDrop(tankNo))

        If checkForStopSignalAndHold(False) Then e.Cancel = True : Exit Sub

        bgwTankStarter.RunWorkerAsync(tankNo + 1)
    End Sub

    Private Sub bgwTankStarter_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgwTankStarter.DoWork
        Dim tankNo As Integer? = CInt(e.Argument)
        If tankNo Is Nothing Then Exit Sub

        'start new tank, or send it to the next level
        If tankNo < oStartStop_Tanks.Length Then
            'start the next tank
            While bgwTanks.IsBusy
                If checkForStopSignalAndHold(False) Then e.Cancel = True : Exit Sub
            End While

            If checkForStopSignalAndHold(False) Then e.Cancel = True : Exit Sub

            bgwTanks.RunWorkerAsync(tankNo)
            stateMessage1 = String.Format("Starting Tank {0}", tankNo + 1)
        Else
            If checkForStopSignalAndHold(False) Then e.Cancel = True : Exit Sub

            UpdateBatchRecord(reportRecordID, txtScales.Text)

            If checkForStopSignalAndHold(False) Then e.Cancel = True : Exit Sub
            'start the next level
            If iLimit_HighStorage Then NumberOfBatchesLeft = 0

            NumberOfBatchesLeft = If(NumberOfBatchesLeft = 0, 0, NumberOfBatchesLeft - 1)

            While Not (iLimit_MixerGateClosed = True And Not inMix)
                If checkForStopSignalAndHold(False) Then e.Cancel = True : Exit Sub
                SleepSecs(2)
                stateMessage1 = String.Format("Wainting for:{0}-Mix to end{0}-MixerGate to Close", vbCrLf)
            End While

            Sakia1AndScrew(2)

            If NumberOfBatchesLeft > 0 Then
                stateMessage1 = String.Format("Starting new cycle of {0} left", NumberOfBatchesLeft)
                If checkForStopSignalAndHold(False) Then e.Cancel = True : Exit Sub
                bgwTanks.RunWorkerAsync(0)
            End If

            While bgwMixer.IsBusy
                If checkForStopSignalAndHold(False) Then e.Cancel = True : Exit Sub
            End While

            If checkForStopSignalAndHold(False) Then e.Cancel = True : Exit Sub

            bgwMixer.RunWorkerAsync()
        End If
    End Sub

    Private Sub Sakia1AndScrew(ByVal delaySecs As Integer)
        oStartStop_Sakia1 = True

        stateMessage1 = String.Format("Starting Sakia1")

        If checkForStopSignalAndHold(False) Then Exit Sub

        SleepSecs(2)

        stateMessage1 = String.Format("Sakia1 Started")

        oStartStop_ScaleScrewMotor = True

        stateMessage1 = String.Format("Screw Started{0}Waiting for zero scale reading", vbCrLf)
        TanksTotalDrop = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}

        If checkForStopSignalAndHold(False) Then Exit Sub

        bgwSiren.RunWorkerAsync()

        LastWeightBeforeDrop = sScaleReading

        While sScaleReading > cTankZeroedValue
            If checkForStopSignalAndHold(True, True, True, True, True, True, True) Then Exit Sub
            SleepSecs(1)
        End While

        stateMessage1 = String.Format("Scale zeroed", vbCrLf)

        If checkForStopSignalAndHold(False) Then Exit Sub

        SleepSecs(2)

        oStartStop_ScaleScrewMotor = False

        For i As Integer = 1 To delaySecs
            If checkForStopSignalAndHold(False) Then Exit Sub
            SleepSecs(1)
        Next

    End Sub

    Private Sub bgwStartMixer_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgwStartMixer.DoWork
        If Not (iLimit_MixerGateClosed = True And oStartStop_ScaleScrewMotor = False) Then
            Dim unit As String = "Mixer Gate and Scale Screw"
            Dim msg As String = String.Format("Cannot start because MixerGate should be closed [{0}]{2}and ScaleScrew should be stopped [{1}]", iLimit_MixerGateClosed, Not oStartStop_ScaleScrewMotor, vbCrLf)
            RaiseAlarm(True, True, False, unit, msg, BatchNo, msg)
            arrAlarms.Add(String.Format("{0}: {1} - {2}", Now, unit, msg))
            stateMessage1 = msg
            Exit Sub
        End If

        oStartStop_Mixer = True

        stateMessage2 = "Starting Mixer"

        If checkForStopSignalAndHold(False) Then e.Cancel = True : Exit Sub

        SleepSecs(2)

        If checkForStopSignalAndHold(False) Then e.Cancel = True : Exit Sub

        If Not iStartStop_MixerACK Then
            StopOperation()
            Dim unit As String = "Mixer"
            Dim msg As String = String.Format("Mixer should be started [{0}]", iStartStop_MixerACK)
            RaiseAlarm(True, True, False, unit, msg, BatchNo, msg)
            arrAlarms.Add(String.Format("{0}: {1} - {2}", Now, unit, msg))
            stateMessage2 = msg
            Exit Sub
        End If

        stateMessage2 = "Mixer Started"

        'bgwTankStarter.RunWorkerAsync(0)
    End Sub

    Private Sub bgwMixer_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgwMixer.DoWork
        If checkForStopSignalAndHold(False) Then e.Cancel = True : Exit Sub

        SleepSecs(2)

        If checkForStopSignalAndHold(False) Then e.Cancel = True : Exit Sub

        oStartStop_Sakia1 = False

        stateMessage2 = String.Format("Sakia1 Stopped{0}Mixing time", vbCrLf)

        inMix = True

        'delay mix time
        For i As Integer = 0 To MixTime
            SleepSecs(1)
            If checkForStopSignalAndHold(True, True, True, True, True, True, True) Then e.Cancel = True : inMix = False : Exit Sub
            stateMessage2 = String.Format("Mixing time : {0}", MixTime - i)
        Next

        oOpenClose_MixerGate = True

        stateMessage2 = String.Format("Mixture Ready{0}To the makbas", vbCrLf)

        'delay mix gate open time
        For i As Integer = 0 To MixerGateOpenTime
            If checkForStopSignalAndHold(False) Then e.Cancel = True : inMix = False : Exit Sub
            SleepSecs(1)
            stateMessage2 = String.Format("Mixer gate time : {0}", MixerGateOpenTime - i)
        Next

        inMix = False

        oOpenClose_MixerGate = False

        stateMessage2 = String.Format("Done", vbCrLf)
    End Sub

    Private Sub spScale_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles spScale.DataReceived
        If TerminateConnection Then
            spScale.Close()
        Else
            Me.Invoke(mymy)
        End If
    End Sub

    Private Sub btnResetHammer_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnResetHammer.Click
        oStartStop_Hammer = False
    End Sub

    Private Sub خلطاتToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles خلطاتToolStripMenuItem.Click
        Mixture.Show()
    End Sub

    Private Sub الارماتToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles الارماتToolStripMenuItem.Click
        alarms.Show()
    End Sub

    Private Sub تقاريرToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles تقاريرToolStripMenuItem.Click
        reports2.Show()
    End Sub

    Private Sub bgwSiren_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgwSiren.DoWork
        oStartStop_Siren = True
        For i As Integer = 1 To 4
            If checkForStopSignalAndHold(False) Then e.Cancel = True : Exit Sub
            SleepSecs(1)
        Next
        oStartStop_Siren = False
    End Sub

    Private Sub btnMixer_StartStop_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnMixer_StartStop.Click
        If oStartStop_Mixer Then
            oStartStop_Mixer = False
        Else
            If Not bgwStartMixer.IsBusy Then bgwStartMixer.RunWorkerAsync()
        End If
    End Sub

    Private Sub btnMixerGate_OpenClose_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnMixerGate_OpenClose.Click
        'oOpenClose_MixerGate = If(Not oOpenClose_MixerGate And iStartStop_MixerACK, True, False)
        oOpenClose_MixerGate = Not oOpenClose_MixerGate
    End Sub

    Private Sub btnSakia1Screw_StartStop_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSakia1Screw_StartStop.Click
        If oStartStop_Sakia1 Then
            oStartStop_Sakia1 = False
            oStartStop_ScaleScrewMotor = False
        Else
            If iStartStop_MixerACK Then bgwManualSakia1AndScrew.RunWorkerAsync()
        End If
    End Sub

    Private Sub bgwManualSakia1AndScrew_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgwManualSakia1AndScrew.DoWork
        fWorking = True
        oStartStop_Sakia1 = True
        SleepSecs(2)
        oStartStop_ScaleScrewMotor = True
        fWorking = False
    End Sub

    Private Sub btnClearList_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnClearList.Click
        lstAlarms.Items.Clear()
    End Sub

    Private Sub main_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        e.Cancel = True
        fForceStop = True
        TerminateConnection = True
        While bgwManualSakia1AndScrew.IsBusy Or bgwMixer.IsBusy Or bgwSiren.IsBusy Or bgwStartMixer.IsBusy Or bgwTanks.IsBusy Or bgwTankStarter.IsBusy
            lstAlarms.Items.Insert(0, "Waiting for background workers to stop...")
            SleepSecs(1)
        End While
        lstAlarms.Items.Insert(0, "Stopping all outputs...")
        ResetAllOutputs()
        If fm.PortOpen Then ConfigureIOPins()
        End
    End Sub

    Private Sub main_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

    End Sub

    Private Sub btnPauseResume_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPauseResume.Click
        fPause = Not fPause
    End Sub
End Class
